<?php

declare (strict_types = 1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://doc.hyperf.io
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
 */
namespace App\Service\Auth;

use App\Constants\ErrorCode;
use App\Dao\AuthAdminLogDao;
use App\Dao\AuthEmployeeDao;
use App\Dao\AuthOrganizationDao;
use App\Dao\CompanyModuleDao;
use App\Dao\ComponentDao;
use App\Dao\DepartComponentDao;
use App\Dao\MenuComponentDao;
use App\Dao\MenuDao;
use App\Dao\ModuleDao;
use App\Exception\BusinessException;
use App\Utils\ApiUtils;
use App\Utils\FunctionUtil;
use App\Utils\Redis;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Codec\Json;

class ModuleService
{

    /**
     * @Inject
     * @var Redis
     */
    protected $redis;

    /**
     * @Inject
     * @var ModuleDao
     */
    protected $mdao;

    /**
     * @Inject
     * @var ComponentDao
     */
    protected $cdao;

    /**
     * @Inject
     * @var MenuDao
     */
    protected $menudao;

    /**
     * @Inject
     * @var MenuComponentDao
     */
    protected $mcdao;

    /**
     * @Inject
     * @var DepartComponentDao
     */
    protected $ddao;

    public function addComponent($params)
    {
        $where = [];
        $where[] = ['module_id', '=', $params['module_id']];
        $where[] = ['url', '=', $params['url']];
        $info = $this->cdao->searchFirst($where);
        if (!empty($info)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '该功能地址已存在');
        }
        $map = [];
        $map['url'] = $params['url'];
        $map['module_id'] = $params['module_id'];
        $map['content'] = $params['content'];
        $map['icon'] = $params['icon'];
        $map['component_name'] = $params['component_name'];
        $id = $this->cdao->add($map);
        return ApiUtils::send(ErrorCode::SUCCESS, '添加成功', $id);

    }

    public function componentCate($params)
    {

        $data = $this->mdao->searchAll([], [], ['module_name', 'id']);
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $data);

    }

    public function editComponent($params)
    {
        $where = [];
        $where[] = ['module_id', '=', $params['module_id']];
        $where[] = ['url', '=', $params['url']];
        $info = $this->cdao->searchFirst($where);
        if (!empty($info) && $info['id'] != $params['id']) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '该功能地址已存在');
        }
        $map = [];
        $map['url'] = $params['url'];
        $map['module_id'] = $params['module_id'];
        $map['content'] = $params['content'];
        $map['icon'] = $params['icon'];
        $map['component_name'] = $params['component_name'];
        $map['update_time'] = \time();
        $where1 = [];
        $where1[] = ['id', '=', $params['id']];
        $id = $this->cdao->update($where1, $map);
        return ApiUtils::send(ErrorCode::SUCCESS, '修改成功', $id);

    }

    public function delComponent($params)
    {
        Db::beginTransaction();
        try {

            $del = [];
            $del[] = ['id', '=', $params['id']];
            $count = $this->cdao->delete($del);
            //删除栏目功能
            $del1 = [];
            $del1[] = ['component_id', '=', $params['id']];
            $this->mcdao->delete($del1);
            //删除部门功能并清除缓存
            $where = [];
            $where[] = ['component_id', '=', $params['id']];
            $ori_ids = $this->ddao->searchOriId($where);
            if (!empty($ori_ids)) {
                foreach ($ori_ids as $v) {
                    $key_permission = config('web.permission_redis_key') . $v;
                    $this->redis->del($key_permission);
                }
            }
            $count = $this->ddao->delete($where);
            Db::commit();
            return ApiUtils::send(ErrorCode::SUCCESS, '删除成功', $count);
        } catch (\Throwable $e) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '删除失败' . config('web.err_msg_splite') . $e->getMessage());
        }

    }

    public function moduleList($params)
    {
        //查找公司开启的模块
        $has = $this->companyMoudleId($params['login_usr']['company_id']);
        //找出已完成的模块
        $sub = $this->componentCate($params);
        $module = $sub['data'];
        foreach ($module as $k => $v) {
            $where = [];
            $where[] = ['module_id', '=', $v['id']];
            $data = [];
            $data = $this->cdao->searchAll($where, [], ['component_name', 'content', 'icon', 'id', 'pid', 'url', 'module_id']);
            if (!empty($data)) {
                $module[$k]['son'] = FunctionUtil::getTree($data);
            }
            if (\in_array($data[0]['module_id'] ?? 0, $has)) {
                $module[$k]['is_open'] = 1;
            } else {
                $module[$k]['is_open'] = 2;
            }
        }
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $module);
    }

    public function insert($data, $sub_module_id, $pid)
    {
        $map = [];
        if (empty($data)) {
            return;
        }
        foreach ($data as $k => $v) {
            $tmp = [];
            $v['pid'] = $pid;
            $tmp['sub_module_id'] = $sub_module_id;
            $tmp['module_name'] = $v['module_name'];
            $tmp['identity'] = $v['identity'];
            $tmp['web_url'] = $v['url'];
            $tmp['pid'] = $v['pid'];
            $res = $this->dao->add($tmp);

            $this->insert($v['son'] ?? [], $sub_module_id, $res);
        }
        $this->dao->insert($map);
    }

    //获取模块功能
    public function getModules($params)
    {
        $arr = [
            [
                'module_name' => '任务管理',
                'identity' => '',
                'url' => '',
                'son' => [
                    [
                        'module_name' => '创建任务',
                        'identity' => '/aoj/fksdl',
                        'url' => 'test',
                    ],
                    [
                        'module_name' => '任务列表',
                        'identity' => '/aoj/fksdl',
                        'url' => 'test',
                    ],
                ],
            ],
            [
                'module_name' => '消息',
                'identity' => '',
                'url' => '',
                'son' => [
                    [
                        'module_name' => '消息列表',
                        'identity' => '/aoj/fksdl',
                        'url' => 'test',
                    ],
                ],
            ],
        ];
        Db::beginTransaction();
        try {
            $pid = 0;
            $this->insert($arr, $params['id'], $pid);

            Db::commit();
            return ApiUtils::send(ErrorCode::SUCCESS, '添加成功', $pid);
        } catch (\Throwable $e) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '添加功能模块失败' . config('web.err_msg_splite') . $e->getMessage());
        }

        // $client = new GRPCClient($params['url']);
        // $request = new Params();
        // $request->setRequest(Json::encode(['appkey'=>$params['appkey']]));
        // $request->setController(TaskService::class);
        // $request->setMethod(__FUNCTION__);

        // list($reply, $status) = $client->curdClient($request);
        // if($reply->getErrCode() == 0){
        //     $data = $reply->getData();
        //     $map = [];
        //     $map['appkey'] = $params['appkey'];
        //     $map['appkey'] = $params['appkey'];
        //     $map['module_name'] = $data['module_name'];
        //     return $this->dao->add($map);
        // }else{
        //     throw new BusinessException(ErrorCode::ERR_BUESSUS, $reply->getMsg());
        // }
    }

    public function EnableModule($params)
    {
        $where = [];
        $where[] = ['id', '=', $params['id']];
        //找出已完成的子模块
        $sub = $this->mdao->searchFirst($where);
        if (!empty($sub)) {
            $has = $this->companyMoudleId($params['login_usr']['company_id']);
            if (in_array($sub['id'], $has)) {
                throw new BusinessException(ErrorCode::ERR_BUESSUS, '模块已开启,请不要重复开启');
            }
            if ($sub['appkey'] == $params['appkey'] && $sub['url'] == $params['url']) {
                $tmp = [];
                $tmp['module_id'] = $params['id'];
                $tmp['company_id'] = $params['login_usr']['company_id'];
                $id = make(CompanyModuleDao::class)->add($tmp);
                make(AuthAdminLogDao::class)->addLog('开启了模块功能' . json_encode($params));
                return ApiUtils::send(ErrorCode::SUCCESS, '开启成功', $id);
            } else {
                throw new BusinessException(ErrorCode::ERR_BUESSUS, '地址或密匙不对');
            }
        } else {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '没有改模块');
        }

    }

    public function componentConfigList($params)
    {

        $data = $this->cdao->pageByWhere([], $params['pageSize']);
        $list = [];
        if (!empty($data['data'])) {
            foreach ($data['data'] as $k => $v) {
                $list[$k]['component_cata'] = $v['module']['module_name'];
                $list[$k]['icon'] = $v['icon'];
                $list[$k]['component_name'] = $v['component_name'];
                $list[$k]['content'] = $v['content'];
                $list[$k]['url'] = $v['url'];
                $list[$k]['add_time'] = $v['add_time'];
                $list[$k]['id'] = $v['id'];
                $list[$k]['cate_id'] = $v['module']['id'];
            }
        }
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $list, $data['total']);
    }

    public function companyModuleList($params)
    {
        //找出已开启的子模块
        $moduleIds = $this->companyMoudleId($params['login_usr']['company_id']);
        $sub = $this->mdao->searchAll([], $moduleIds, ['module_name', 'id']);
        foreach ($sub as $k => $v) {
            $where = [];
            $where[] = ['module_id', '=', $v['id']];
            $data = [];
            $data = $this->cdao->searchAll($where, [], ['component_name', 'content', 'icon', 'id', 'pid', 'url']);
            if (!empty($data)) {
                $sub[$k]['son'] = FunctionUtil::getTree($data);
            } else {
                $sub[$k]['son'] = [];
            }

        }
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $sub);
    }

    //查找公司开启的模块id
    public function companyMoudleId($company_id)
    {
        $where = [];
        $where[] = ['company_id', '=', $company_id];
        return make(CompanyModuleDao::class)->searchMoudleId($where);
    }

    public function departAddComponent($params)
    {
        $component = \explode(',', $params['component_id']);
        $component = array_unique($component);
        Db::beginTransaction();
        try {
            //删除之前
            $where = [];
            $where[] = ['org_id', '=', $params['org_id']];
            $has = $this->ddao->delete($where);
            $map = [];
            foreach ($component as $k => $v) {
                if (empty($v)) {
                    continue;
                }
                $tmp = [];
                $tmp['component_id'] = $v;
                $tmp['org_id'] = $params['org_id'];
                $tmp['company_id'] = $params['login_usr']['company_id'];
                $map[] = $tmp;
            }
            $count = $this->ddao->insert($map);
            make(AuthOrganizationDao::class)->updateByIdTrait(['id' => $params['org_id'], 'cover_next' => $params['cover_next']]);
            make(AuthAdminLogDao::class)->addLog('部门添加了模块' . json_encode($params));
            Db::commit();
            $key_permission = config('web.permission_redis_key') . $params['org_id'];
            $this->redis->del($key_permission);
            return ApiUtils::send(ErrorCode::SUCCESS, '添加成功', $count);

        } catch (\Throwable $e) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '添加部门权限失败' . config('web.err_msg_splite') . $e->getMessage());
        }
    }

    //部门已被分配的模块
    public function departHasComponent($params)
    {
        $where = [];
        $where[] = ['org_id', '=', $params['org_id']];
        $list = $this->ddao->searchComponentId($where);

        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $list);

    }

    //查找部门权限(树形结构)
    public function searchDepartModule($moduleIds, $company_id)
    {
        if (!empty($moduleIds)) {
            $where = [];
            $where[] = ['company_id', '=', $company_id];
            //找出栏目列表
            $list = $this->menudao->searchAll($where);
            foreach ($list as $k => $v) {
                $where1 = [];
                $where1[] = ['menu_id', '=', $v['id']];
                //找出每个栏目下自己的模块
                $module_ids = $this->mcdao->searchMoudleIdByModule($where1, $moduleIds);
                //找出模块的顶级id 因为部门权限没存顶级id
                // $where2 = [];
                // $where2[] = ['pid','=', 0];
                // $p_ids = $this->dao->searchAllId($where2);
                // $module_ids = array_merge($module_ids,$p_ids);
                if (empty($module_ids)) {
                    unset($list[$k]);
                    continue;
                }
                $module = [];
                //把模块追加到栏目下
                $module = $this->cdao->searchAll([], $module_ids, ['id', 'component_name', 'url', 'pid']);
                $list[$k]['module'] = $module;
                unset($list[$k]['modules']);
            }
        } else {
            $list = [];
        }

        return array_values($list);
    }

    /**
     * 获取当前用户员工部门权限模块
     *
     * @Author czm
     * @DateTime 2020-09-29
     * @param [type] $params
     * @return void
     */
    public function userHasModule($params)
    {
        $employee = make(AuthEmployeeDao::class)->findTrait($params['employee_id']);

        $org_id = $employee->organization_id;
        $componentIds = [];
        while ($org_id && empty($componentIds)) {
            $componentIds = $this->departHasComponent(['org_id' => $org_id])['data'] ?? [];
            //查找上级下发的权限模块
            $org_id = make(AuthOrganizationDao::class)->findTopCover($org_id);
        }

        $permission = $this->searchDepartModule($componentIds, $employee->company_id);
        $key_permission = config('web.permission_redis_key') . $employee->organization_id;
        $this->redis->set($key_permission, Json::encode($permission), ['EX' => 86400]);
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', ['cache_key' => $key_permission, 'db' => env('REDIS_DB', 0)]);

    }

}
